<template>
  <div class="app-content" ref="containerRef" style="height: 800px"></div>
</template>

<script>
import { Graph, Node, Edge, Shape } from "@antv/x6";
import { register } from "@antv/x6-vue-shape";
import Hierarchy from "@antv/hierarchy";
import TreeNode from "./treeNode.vue";
import ContentNode from "./contentNode.vue";
import MethodNode from "./methodNode.vue";

export default {
  name: "ModelGraphChart",
  components: {},
  data() {
    return {
      graph: null,
      graphChart: null
    };
  },
  mounted() {
    this.register();
  },
  methods: {
    register() {
      register({
				shape: 'tree-node',
				width: 140,
				height: 40,
				component: {
          render: (h) =>
            h(TreeNode, {
              on: {
                expandChildren: (type, cnode) => {
                  this.updateData(type, cnode)
                },
              },
            }),
        },
        ports: {
          groups: {
            left: {
              position: 'left',
              attrs: {
                circle: {
                  display:'none',
                  r: 6,
                  magnet: true,
                  stroke: '#1f89cc',
                  strokeWidth: 2,
                  fill: '#fff',
                },
              },
            },
            right: {
              position: 'right',
              attrs: {
                circle: {
                  display:'none',
                  r: 6,
                  magnet: true,
                  stroke: '#1f89cc',
                  strokeWidth: 2,
                  fill: '#fff',
                },
              },
            },
          },
        },
			})
			register({
				shape: 'target-node',
				width: 280,
				height: 136,
				component: {
          render: (h) =>
            h(ContentNode, {
              on: {
                expandChildren: (data,a) => {
                  console.log(data,a)
                },
              },
            }),
        },
        ports: {
          groups: {
            left: {
              position: 'left',
              attrs: {
                circle: {
                  display:'none',
                  r: 6,
                  magnet: true,
                  stroke: '#1f89cc',
                  strokeWidth: 2,
                  fill: '#fff',
                },
              },
            },
            right: {
              position: 'right',
              attrs: {
                circle: {
                  display:'none',
                  r: 6,
                  magnet: true,
                  stroke: '#1f89cc',
                  strokeWidth: 2,
                  fill: '#fff',
                },
              },
            },
          },
        },
			})
      register({
				shape: 'method-node',
				width: 140,
				height: 60,
				component: {
          render: (h) =>
            h(MethodNode, {
              on: {
                change: (data,a) => {
                  console.log(data,a)
                },
              },
            }),
        },
        ports: {
          groups: {
            left: {
              position: 'left',
              attrs: {
                circle: {
                  display:'none',
                  r: 6,
                  magnet: true,
                  stroke: '#1f89cc',
                  strokeWidth: 2,
                  fill: '#fff',
                },
              },
            },
          },
        },
			})
			// 边
      Graph.registerEdge(
        "model-edge",
        {
          inherit: "edge",
          attrs: {
            line: {
              stroke: '#004892',
              strokeWidth: 1,
              targetMarker: {
                name: 'classic',
              },
            },
          },
          connector: {
            name: "smooth",
          },
          zIndex: 0,
        },
        true
      );
    },
    init(data) {
      this.graphChart = data
			const that = this
      const containerRef = this.$refs.containerRef;
      const graph = new Graph({
        container: containerRef,
        autoResize: true,
        // interacting: {
        //   nodeMovable: false
        // }
        // connecting: {
        //   connectionPoint: "anchor",
        // },
        // mousewheel: {
        //   enabled: true,
        //   minScale: 0.1,
        //   maxScale: 4,
        // },
        // panning: {
        //   enabled: true,
        // },
        // interacting: {
        //   nodeMovable: false,
        // },
        // keyboard: {
        //   enabled: true,
        // },
      });
      this.graph = graph;
      
			const render = () => {
        const result = Hierarchy.mindmap(data, {
          direction: "H",
          getHeight(d) {
            return d.height;
          },
          getWidth(d) {
            return d.width;
          },
          getHGap() {
            return 10;
          },
          getVGap() {
            return 10;
          },
          getSide: () => {
            return "right";
          },
        });

        const cells = [];
        const traverse = (hierarchyItem) => {
          if (hierarchyItem) {
            const { data, children, parent = null } = hierarchyItem;
            console.log(hierarchyItem)
            if (data.shape === 'tree-node') {
              cells.push(
                graph.createNode({
                  id: data.id,
                  shape: data.shape,
                  x: data.x,
                  y: hierarchyItem.y,
                  width: data.width,
                  height: data.height,
                  label: data.label,
                  type: data.type,
                  visible: data.id === 'none' ? false : parent.data.isActived,
                  ports: {
                    items: [
                      {
                        id: 'port_left'+data.id,
                        group: 'left',
                      },
                      {
                        id: 'port_right'+data.id,
                        group: 'right',
                      },
                    ],
                  },
                  data,
                })
              );
            } else if (data.shape === 'target-node') {
              cells.push(
                graph.createNode({
                  id: data.id,
                  shape: data.shape,
                  x: data.x,
                  y: hierarchyItem.y,
                  width: data.width,
                  height: data.height,
                  label: data.label,
                  type: data.type,
                  visible: parent.data.isActived,
                  ports: {
                    items: [
                      {
                        id: 'port_left'+data.id,
                        group: 'left',
                      },
                      {
                        id: 'port_right'+data.id,
                        group: 'right',
                      },
                    ],
                  },
                  data,
                })
              )
            } else if (data.shape === 'method-node') {
              cells.push(
                graph.createNode({
                  id: data.id,
                  shape: data.shape,
                  x: data.x,
                  y: hierarchyItem.y,
                  width: data.width,
                  height: data.height,
                  label: data.label,
                  type: data.type,
                  visible: parent.data.isActived,
                  ports: {
                    items: [
                      {
                        id: 'port_left'+data.id,
                        group: 'left',
                      },
                    ],
                  },
                  data,
                })
              )
            }
            
            if (children) {
              children.forEach((item) => {
                const { id, data } = item;
                cells.push(
                  graph.createEdge({
                    shape: "model-edge",
                    connector: {
                      name: data.shape === 'method-node' ? 'normal' : 'smooth',
                    },
                    source: {
                      cell: hierarchyItem.data.id,
                      port: 'port_right'+hierarchyItem.data.id,
                    },
                    target: {
                      cell: id,
                      port: 'port_left'+id,
                    },
                  })
                )

                traverse(item);
              });
            }
          }
        };
        traverse(result);
        graph.resetCells(cells);
        graph.positionContent('left')
      };
      // this.graph.render = render
      // 渲染
      render();
    },
    updateData(type, cnode) {
      const idArr = cnode.data.id.split('-')
      const run = (pre) => {
        const succ = this.graph.getSuccessors(pre, { distance: 1 })
        console.log(succ)
        if (succ) {
          succ.forEach((node) => {
            node.visible = !node.visible
            // content和method一起显示隐藏
            if (node.data.type === 'content' && node.data.children && node.data.children.length) {
              run(node)
            } else if (node.data.isActived) {
              run(node)
            }
          })
        }
      }
      const update = (list) => {
        if (list && list.length) {
          list.forEach(item => {
            if (item.id !== cnode.data.id) {
              if (!cnode.data.id.includes(item.id)) {
                const cell = this.graph.getCellById(item.id)
                if (cell.data.isActived) {
                  cell.data.isActived = false
                  run(cell)
                }
              }
              
              if (item.children && item.children.length) {
                update(item.children)
              }
            }
          })
        }
      }

      update(this.graphChart.children)

      // 展开
      if (type === 'expand') {
        cnode.data.isActived = true
        if (idArr[2]) {
          const cell1 = this.graph.getCellById(`${idArr[0]}-${idArr[1]}`)
          const cell2 = this.graph.getCellById(`${idArr[0]}`)
          cell1.data.isActived = true
          cell2.data.isActived = true
        } else if (idArr[1]) {
          const cell2 = this.graph.getCellById(`${idArr[0]}`)
          cell2.data.isActived = true
        }
      } else {
        cnode.data.isActived = false
      }
      
      run(cnode)
    }
  },
};
</script>

<style lang="scss" scoped>
</style>